/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package com.icee.myth.server.index;

import com.icee.myth.log.GameLogger;
import com.icee.myth.log.message.FileDebugGameLogMessage;
import com.icee.myth.log.message.builder.GameLogMessageBuilder;
import com.icee.myth.server.GameServer;
import com.icee.myth.server.actor.Human;
import com.icee.myth.server.base.BaseTarget;
import com.icee.myth.server.base.occupy.OccupyInfo;
import com.icee.myth.server.base.occupy.OccupyInfos;
import java.util.ArrayList;
import java.util.NavigableSet;
import java.util.TreeSet;

/**
 * 
 * @author liuxianke
 */
public class PlayerIdsOfLevel {
    private final TreeSet<Integer> playerIds = new TreeSet<Integer>();

    // lastSearchPlayerId记录上次查询助战玩家到达的id。每次查询列表时，都从lastSearchPlayerId开始向后查询playerIds表，若查到表末则循环从表头开始找，
    // 但每次查询最多从lastSearchPlayerId+1到表末，再从表头到lastSearchPlayerId
    public int lastSearchPlayerId;

    public PlayerIdsOfLevel() {
    }

    public void add(int playerId) {
        if (!playerIds.add(playerId)) {
            GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                    FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                    "Player[" + playerId + "] multi-add in same level set."));
        }
    }

    public void remove(int playerId) {
        if (!playerIds.remove(playerId)) {
            GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                    FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                    "Player[" + playerId + "] not in level set when remove from it."));
        }
    }

    public int count() {
        return playerIds.size();
    }

    /**
     * 判断是否有目标（不能是玩家本人或其君主或其臣属）
     * @param human
     * @param occupyInfo
     * @return true:有目标 false:无目标
     */
    public boolean hasBaseTarget(Human human, OccupyInfo occupyInfo) {
        for (Integer playerId : playerIds) {
            if ((playerId != human.id) &&   // 不是自己
                ((occupyInfo.king == null) || (playerId != occupyInfo.king.id)) &&  // 不是君主
                (occupyInfo.getCapeCollinson(playerId) == null)) {  // 不是臣属
                return true;
            }
        }

        return false;
    }

    /**
     * 为human选取下一个目标，目标不能是玩家本身或其君主或其臣属
     * @param human
     * @param resultTargets 目标添加到此列表中
     * @return true:选择了目标 false:未选择目标
     */
    public boolean getBaseTarget(Human human, OccupyInfo occupyInfo, ArrayList<BaseTarget> resultTargets) {
        // 先从lastSearchPlayerId开始的后续表中搜索符合条件的目标，找到则返回
        NavigableSet<Integer> tailSet = playerIds.tailSet(lastSearchPlayerId, false);
        for (Integer playerId : tailSet) {
            if (playerId != human.id) { // 不是自己
                if ((occupyInfo.king == null) || (playerId != occupyInfo.king.id)) { // 不是君主
                    if (occupyInfo.getCapeCollinson(playerId) == null) { // 不是臣属
                        // 目标玩家数据一定在内存，否则报错
                        Human targetHuman = GameServer.INSTANCE.getHuman(playerId);
                        if (targetHuman != null) {
                            OccupyInfo targetOccupyInfo = OccupyInfos.INSTANCE.getOccupyInfo(playerId);
                            if (targetOccupyInfo != null) {
                                if (targetOccupyInfo.inited) {  // 只选择已经初始化好的玩家
                                    // 判断目标是否已被选过，若已选过返回false
                                    for (BaseTarget target : resultTargets) {
                                        if (target.id == playerId) {
                                            return false;
                                        }
                                    }

                                    resultTargets.add(new BaseTarget(targetHuman, (targetOccupyInfo.king != null)));
                                    lastSearchPlayerId = playerId;
                                    return true;
                                }
                            } else {
                                GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                                        FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                                        "Human[" + playerId + "] in memory but occupy info not in memory"));
                            }
                        } else {
                            GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                                    FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                                    "Human[" + playerId + "] in PlayerIdsOfLevel but not in memory"));
                        }
                    }
                }
            }
        }
        
        // 再从头到lastSearchPlayerId为止的前置表中搜索符合条件的目标，找到则返回
        NavigableSet<Integer> headSet = playerIds.headSet(lastSearchPlayerId, true);
        for (Integer playerId : headSet) {
            if (playerId != human.id) { // 不是自己
                if ((occupyInfo.king == null) || (playerId != occupyInfo.king.id)) { // 不是君主
                    if (occupyInfo.getCapeCollinson(playerId) == null) { // 不是臣属
                        // 目标玩家数据一定在内存，否则报错
                        Human targetHuman = GameServer.INSTANCE.getHuman(playerId);
                        if (targetHuman != null) {
                            OccupyInfo targetOccupyInfo = OccupyInfos.INSTANCE.getOccupyInfo(playerId);
                            if (targetOccupyInfo != null) {
                                if (targetOccupyInfo.inited) {  // 只选择已经初始化好的玩家
                                    // 判断目标是否已被选过，若已选过返回false
                                    for (BaseTarget target : resultTargets) {
                                        if (target.id == playerId) {
                                            return false;
                                        }
                                    }
                                    
                                    resultTargets.add(new BaseTarget(targetHuman, (targetOccupyInfo.king != null)));
                                    lastSearchPlayerId = playerId;
                                    return true;
                                }
                            } else {
                                GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                                        FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                                        "Human[" + playerId + "] in memory but occupy info not in memory"));
                            }
                        } else {
                            GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                                    FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                                    "Human[" + playerId + "] in PlayerIdsOfLevel but not in memory"));
                        }
                    }
                }
            }
        }

        return false;
    }
}
